package family.gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

/**
 * This is the controller class which is based on events, controller calls
 * methods in model. Controller registers for and processes view events.
 * 
 * @author Edis Dilji
 * @version 5.0, December 23, 2012
 */

// CLASSDEFINITION
public class Controller implements ActionListener, KeyListener {

	// In this class at first part we listen for button clicks,
	// at second part we listen for key press
	// and at third part are all methods for button clicks.

	// Links to model and view class
	private Model model;
	private View view;

	// VARIABLES
	protected String nam;
	protected String gend;
	protected String fath;
	protected String moth;
	protected String[] parentsOf = new String[2];
	protected String[] grandParentsOf = new String[6];
	protected String children;
	protected String printStatus;
	protected String replyShowParents;
	protected String replyShowGrandParents;
	protected String replyShowChildren;

	/**
	 * Controller class constructor.
	 */

	protected Controller(Model model, View view) {

		// link to model and view object
		this.model = model;
		this.view = view;

		// register ourselves to listen for button clicks
		view.jb_addPerson.addActionListener(this);
		view.jb_getGrandparents.addActionListener(this);
		view.jb_getParents.addActionListener(this);
		view.jb_getChildren.addActionListener(this);
		view.jb_help.addActionListener(this);
		view.jb_exit.addActionListener(this);
		view.jb_back.addActionListener(this);
		view.jb_createPerson.addActionListener(this);
		view.jb_helpBack.addActionListener(this);
		view.jb_helpAddPerson.addActionListener(this);

		// register ourselves to listen for key press
		view.addKeyListener(this);
		view.setFocusable(true);
	}

	// ***********************************************************************************************
	// *                                                                                             *
	// * Listen for button clicks                                                                    *
	// *                                                                                             *
	// ***********************************************************************************************

	/*
	 * verify which button was clicked
	 * 
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */

	@Override
	public void actionPerformed(ActionEvent e) {

		// delete text in JTextfield if present
		view.jta_relation.setText(null);

		// button addPerson
		if (e.getSource() == view.jb_addPerson) {
			// show action in "status" and call addPersonView
			view.jl_status.setText("Last action: add Person");
			view.addPersonView();

		// button getParents
		} else if (e.getSource() == view.jb_getParents) {
			// show action in "status" and call actGetParents-method
			view.jl_status.setText("Last action: get Parents");
			actGetParents();

		// button getGrandparents
		} else if (e.getSource() == view.jb_getGrandparents) {
			// show action in "status" and call actGetGrandParents-method
			view.jl_status.setText("Last action: get Grandparents");
			actGetGrandparents();

		// button getChildren
		} else if (e.getSource() == view.jb_getChildren) {
			// show action in "status" and call actGetChildren-method
			view.jl_status.setText("Last action: get Children");
			actGetChildren();

		// button help
		} else if (e.getSource() == view.jb_help) {
			// show action in "status" and call helpView
			view.jl_status.setText("Last action: help");
			view.helpView();

		// button exit
		} else if (e.getSource() == view.jb_exit) {
			// show action in "status" and end mainProgram
			view.jl_status.setText("Last action: Exit");
			Main.getMainProgram().endMainProgram();

		// button back
		} else if (e.getSource() == view.jb_back) {
			// show action in "status" and call addPersonViewBackButton
			view.jl_status.setText("Last action: cancel");
			view.addPersonViewBackButton();

		// button createPerson
		} else if (e.getSource() == view.jb_createPerson) {
			// show action in "status" and call actCreatePerson-method
			view.jl_status.setText("Last action: create person");
			actCreatePerson();

		// button ok at help view
		} else if (e.getSource() == view.jb_helpBack) {
			// show action in "status" and call helpView
			view.jl_status.setText("Last action: back");
			view.helpViewOkButton();

		// button addPerson at help view
		} else if (e.getSource() == view.jb_helpAddPerson) {
			// show action in "status" and call addPersonView
			view.jl_status.setText("Last action: add person");
			view.helpViewAddPersonButton();
		}
	}

	// ***********************************************************************************************
	// *                                                                                             *
	// * Listen for key actions                                                                      *
	// *                                                                                             *
	// ***********************************************************************************************

	/*
	 * Listen which key was pressed
	 * 
	 * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
	 */

	@Override
	public void keyPressed(KeyEvent e) {

		// listen for escape press and show in "status"
		if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
			view.jl_status.setText("Last action: Exit");

		// listen for F1 press and show in "status"
		} else if (e.getKeyCode() == KeyEvent.VK_F1) {
			view.jl_status.setText("Last action: 'F1' pressed (add Person)");

		// listen for F2 press and show in "status"
		} else if (e.getKeyCode() == KeyEvent.VK_F2) {
			view.jl_status.setText("Last action: 'F2' pressed (help)");

		// listen for all other keys and show in "status" which key was pressed
		} else {
			if ((KeyEvent.getKeyText(e.getKeyCode())).equals("Unknown keyCode: 0x0")) {
				// if unknown key was pressed, show this in "status"
				view.jl_status.setText("Last action: Unknown key pressed");
			} else {
				// show in "status" which key was pressed
				view.jl_status.setText("Last action: '" + KeyEvent.getKeyText(e.getKeyCode()) + "' pressed");
			}
		}

	}

	/*
	 * Listen which key was released
	 * 
	 * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)
	 */

	@Override
	public void keyReleased(KeyEvent e) {

		// listen for escape press and end program
		if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
			Main.getMainProgram().endMainProgram();

		// listen for F1 press and set addPersonView
		} else if (e.getKeyCode() == KeyEvent.VK_F1) {
			view.jp_left.setVisible(true);
			view.meuAddPersonView();

		// listen for F2 press and set helpView
		} else if (e.getKeyCode() == KeyEvent.VK_F2) {
			view.meuHelpView();
		}

	}

	/*
	 * Listen which key was typed (not used)
	 * 
	 * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
	 */

	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub

	}

	// ***********************************************************************************************
	// *                                                                                             *
	// * Methods for button clicks                                                                   *
	// *                                                                                             *
	// ***********************************************************************************************

	// METHOD actGetParents - get parents of person and show them
	public void actGetParents() {
		
		// get selected name of list at GUI
		String selName = (String) view.jlist.getSelectedValue();

		// continue if only a name is selected 
		if (selName != null) {
			
			// delete gender-information at selected name, such as 'edis (m)'
			// is selected, delete ' (m)' and continue only with name 'edis'
			String name = selName.substring(0, selName.length() - 4);
			
			// call method showParents from model class and write results in
			// string-array 'parentsOf[2]' -> [0] is father and [1] is mother
			this.parentsOf = model.showParents(name);

			// if no parents are registered, show this
			if ((parentsOf[0] == null) && (parentsOf[1] == null)) {
				replyShowParents = "For '" + name + "' are no parents registered";
			// if only father is registered, show this
			} else if ((parentsOf[0] != null) && (parentsOf[1] == null)) {
				replyShowParents = "Father of '" + name + "' is '" + parentsOf[0] + "', mother is not or wrong registered";
			// if only mother is registered, show this
			} else if ((parentsOf[0] == null) && (parentsOf[1] != null)) {
				replyShowParents = "Mother of '" + name + "' is '" + parentsOf[1] + "', father is not or wrong registered";
			// if parents are registered, show this
			} else if ((parentsOf[0] != null) && (parentsOf[1] != null)) {
				replyShowParents = "Parents of '" + name + "' are '" + parentsOf[0] + "' (father) and '" + parentsOf[1] + "' (mother)";
			// show warning message
			} else {
				replyShowParents = "Something is wrong, please try it again";
			}

		// if no person was selected, request user to select a person
		} else {
			replyShowParents = "Please select a person of the left list";
		}
		
		// finally show the correct message at GUI
		view.jta_relation.setText(replyShowParents);
		
	}

	// METHOD actGetGrandParents - get grandparents of person and show them
	public void actGetGrandparents() {
		
		// delete all at reply of this method
		replyShowGrandParents = null;

		// get selected name of list at GUI
		String selName = (String) view.jlist.getSelectedValue();

		// continue if only a name is selected 
		if (selName != null) {
			
			// delete gender-information at selected name, such as 'edis (m)'
			// is selected, delete ' (m)' and continue only with name 'edis'
			String selectedName = selName.substring(0, selName.length() - 4);
			
			// call method showGrandParents from model class and write results in
			// string-array 'grandParentsOf[6]' by following content:
			// [0]=father -> [1]=grandfather; [2]=grandmother
			// [3]=mother -> [4]=grandfather; [5]=grandmother
			this.grandParentsOf = model.showGrandparents(selectedName);

			// *******************************************************************
			// check father site
			// *******************************************************************
			// if only grandfather is registered, show this
			if ((grandParentsOf[1] != null) && (grandParentsOf[2] == null)) {
				replyShowGrandParents = selectedName + "'s grandfather (" + grandParentsOf[0] + "'s father) is '" + grandParentsOf[1] + "'" + " and grandmother (" + grandParentsOf[0] + "'s mother) is not registered";
			}
			// if only grandmother is registered, show this
			if ((grandParentsOf[1] == null) && (grandParentsOf[2] != null)) {
				// if reply is empty set new reply, else append new reply
				if (replyShowGrandParents == null) {
					replyShowGrandParents = selectedName + "'s grandmother (" + grandParentsOf[0] + "'s mother) is '" + grandParentsOf[2] + "'" + " and grandfather (" + grandParentsOf[0] + "'s father) is not registered";
				} else {
					replyShowGrandParents += "\n\n" + selectedName + "'s grandmother (" + grandParentsOf[0] + "'s mother) is '" + grandParentsOf[2] + "'" + " and grandfather (" + grandParentsOf[0] + "'s father) is not registered";
				}
			}

			// *******************************************************************
			// check mother site
			// *******************************************************************
			// if only grandfather is registered, show this
			if ((grandParentsOf[4] != null) && (grandParentsOf[5] == null)) {
				// if reply is empty set new reply, else append new reply
				if (replyShowGrandParents == null) {
					replyShowGrandParents = selectedName + "'s grandfather (" + grandParentsOf[3] + "'s father) is '" + grandParentsOf[4] + "'" + " and grandmother (" + grandParentsOf[3] + "'s mother) is not registered";
				} else {
					replyShowGrandParents += "\n\n" + selectedName + "'s grandfather (" + grandParentsOf[3] + "'s father) is '" + grandParentsOf[4] + "'" + " and grandmother (" + grandParentsOf[3] + "'s mother) is not registered";
				}
			}
			// if only grandmother is registered, show this
			if ((grandParentsOf[4] == null) && (grandParentsOf[5] != null)) {
				// if reply is empty set new reply, else append new reply
				if (replyShowGrandParents == null) {
					replyShowGrandParents = selectedName + "'s grandmother (" + grandParentsOf[3] + "'s mother) is '" + grandParentsOf[5] + "'" + " and grandfather (" + grandParentsOf[3] + "'s father) is not registered";
				} else {
					replyShowGrandParents += "\n\n" + selectedName + "'s grandmother (" + grandParentsOf[3] + "'s mother) is '" + grandParentsOf[5] + "'" + " and grandfather (" + grandParentsOf[3] + "'s father) is not registered";
				}
			}
			
			// *******************************************************************
			// check father site for both grandparents
			// *******************************************************************
			// if both grandparents are registered, overwrite reply with both grandparents
			if ((grandParentsOf[1] != null) && (grandParentsOf[2] != null)) {
				replyShowGrandParents = selectedName + "'s grandfather (" + grandParentsOf[0] + "'s father) is '" + grandParentsOf[1] + "'" + " and grandmother (" + grandParentsOf[0] + "'s mother) is '" + grandParentsOf[2] + "'";
			}
			
			// *******************************************************************
			// check mother site for both grandparents
			// *******************************************************************
			// if both grandparents are registered, overwrite reply with both grandparents
			if ((grandParentsOf[4] != null) && (grandParentsOf[5] != null)) {
				// if reply is empty set new reply, else append reply
				if (replyShowGrandParents == null) {
					replyShowGrandParents = selectedName + "'s grandfather (" + grandParentsOf[3] + "'s father) is '" + grandParentsOf[4] + "'" + " and grandmother (" + grandParentsOf[3] + "'s mother) is '" + grandParentsOf[5] + "'";
				} else {
					replyShowGrandParents += "\n\n" + selectedName + "'s grandfather (" + grandParentsOf[3] + "'s father) is '" + grandParentsOf[4] + "'" + " and grandmother (" + grandParentsOf[3] + "'s mother) is '" + grandParentsOf[5] + "'";
				}
			}

			// *******************************************************************
			// check if no grandparents are registered
			// *******************************************************************
			// if no grandparents and no parents are registered, overwrite reply
			if ((grandParentsOf[0] == null) && (grandParentsOf[1] == null) && (grandParentsOf[2] == null) && (grandParentsOf[3] == null) && (grandParentsOf[4] == null) && (grandParentsOf[5] == null)) {
				replyShowGrandParents = "For '" + selectedName + "' are no grandparents registered, but also are no parents registered";
			// if only no grandparents are registered, overwrite reply
			} else if ((grandParentsOf[1] == null) && (grandParentsOf[2] == null) && (grandParentsOf[4] == null) && (grandParentsOf[5] == null)) {
				replyShowGrandParents = "For '" + selectedName + "' are no grandparents registered";
			}

		// if no person was selected, request user to select a person
		} else {
			replyShowGrandParents = "Please select a person of the left list";
		}

		// finally show the correct message at GUI
		view.jta_relation.setText(replyShowGrandParents);
	}

	// METHOD actGetChildren - get children of person and show them
	public void actGetChildren() {
		
		// get selected name of list at GUI
		String selName = (String) view.jlist.getSelectedValue();

		// continue if only a name is selected 
		if (selName != null) {
			
			// delete gender-information at selected name, such as 'edis (m)'
			// is selected, delete ' (m)' and continue only with name 'edis'
			String name = selName.substring(0, selName.length() - 4);
			
			// call method showChildren from model class and write results in
			// string 'children', whereat this string is for view already conditioned
			this.children = model.showChildren(name);

			// if person has children, show them
			if (children != null) {
				this.replyShowChildren = "The children of '" + name + "' are:\n" + children;
			// if person has no children, show this
			} else if (children == null) {
				this.replyShowChildren = "'" + name + "' has no children";
			// warning message
			} else {
				this.replyShowChildren = "Something is wrong, please try it again";
			}
			
		// if no person was selected, request user to select a person
		} else {
			replyShowChildren = "Please select a person of the left list";
		}
		
		// finally show the correct message at GUI
		view.jta_relation.setText(replyShowChildren);
	}

	// METHOD actCreatePerson - add new person to program
	public void actCreatePerson() {
		
		// if radioButton 'male' is active, write in string gend 'm'
		if ((view.maleButton.isSelected()) == true) {
			this.gend = "m";
		// if radioButton 'female' is active, write in string gend 'f'
		} else if ((view.femaleButton.isSelected()) == true) {
			this.gend = "f";
		// if no radioButton is active, write in string gend 'nogender'
		} else {
			this.gend = "nogender";
		}

		// get entered name 'nam'
		this.nam = view.jtf_name.getText();
		// get entered father to string 'fath'
		this.fath = view.jtf_father.getText();
		// get entered mother to string 'moth'
		this.moth = view.jtf_mother.getText();

		// if no name was entered, show this in "status"
		if ((nam.equals(""))) {
			// set this warning red
			view.jl_status.setText("<html><div style=\"color: red;\">" + "Warning: Please enter a name to create a new person" + "</html>");
		
		// if no gender was selected, show this in "status"
		} else if (gend.equals("nogender")) {
			// set this warning red
			view.jl_status.setText("<html><div style=\"color: red;\">" + "Warning: Please select gender (male or female)" + "</html>");
		
		// continue only if name and gender are well
		} else {
			
			// call method addNewPerson from model class and write results in
			// string 'printStatus'
			this.printStatus = model.addNewPerson(nam, gend, fath, moth);
			
			// write reply (results) of method 'addNewPerson' in "status"
			view.jl_status.setText(printStatus);
			
			// don't refresh window, if reply (results) of method 'addNewPerson' have an warning
			if ((printStatus.equals("Please verify: father is not male")) || (printStatus.equals("Please verify: mother is not female")) || (printStatus.equals("Please select gender (male or female)"))) {
			
			// refresh window, if reply (results) is ok
			} else {
				// set new created person with gender to list at GUI
				view.addNewNameToJlist(nam + " (" + gend + ")");
				// refresh window, also go back to main view
				view.addPersonViewBackButton();
			}
		}
	}
}